/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.knn;

import java.io.Serializable;

import phoside.data.feature.model.Instance;
import phoside.data.feature.model.InstanceUtil;

import phoside.knn.matrix.similarity.MatrixUtils;
import phoside.knn.matrix.similarity.SimilarityMatrix;

/**
 *
 * @author gjj
 */
public class SequenceBasedClosenessCalculator implements ClosenessCalculator, Serializable {
    private static final long serialVersionUID = -82979909064557117L;
    
    protected final double[][] matrix;
    final int windowOffset;

    public SequenceBasedClosenessCalculator(final SimilarityMatrix simMatrix,
            final int windowOffset) {
        if (simMatrix==null) {
            throw new NullPointerException();
        }

        if (windowOffset<=0) {
            throw new IllegalArgumentException();
        }
        
        this.matrix = MatrixUtils.reindexByASCii(simMatrix);
        this.windowOffset = windowOffset;
    }

    public int getWindowOffset() {
        return windowOffset;
    }

    /**
     * 
     * @param instance1
     * @param instance2
     * @return
     */
    public double calculate(final Instance instance1,
                            final Instance instance2) {
        if (instance1==null || instance2==null) {
            throw new java.lang.NullPointerException();
        }
       
        String seq1 = InstanceUtil.extractSurroundingSequence(instance1, 
                windowOffset, true);

        String seq2 = InstanceUtil.extractSurroundingSequence(instance2, 
                windowOffset, true);

        if (seq1==null || seq2==null)
            throw new IllegalArgumentException();

        double return_this = 0;
        for (int i=0; i<windowOffset; i++) {
            // ignore the center
                return_this += matrix[seq1.charAt(i)][seq2.charAt(i)];
                return_this += matrix[seq1.charAt(windowOffset+i+1)][seq2.charAt(windowOffset+i+1)];
        }

        return_this /= 2*windowOffset;

        return return_this;
    }
}
